package com.example.sdtreader;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import androidx.annotation.NonNull;

import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.text.InputType;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.text.method.ScrollingMovementMethod;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;


import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import com.aliyun.facebody20191230.models.CompareFaceAdvanceRequest;
import com.aliyun.facebody20191230.models.CompareFaceResponse;
import com.aliyun.facebody20191230.models.DetectFaceResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaModel;
import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions;
import com.example.sdtreader.R;



import com.example.Utils.ImageUtil;
import com.example.Utils.*;
import com.sdtapi.jni.*;
import com.sdtapi.jni.JNISDTReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.Set;

import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.Manifest;
import android.content.pm.PackageManager;
import android.widget.Toast;

public class FaceActivity extends AppCompatActivity {

    private static final int CHANGE_TEXT = 1;
    private static final int CLEAR_TEXT = 0;

    private static UsbDeviceHelper g_usbHelp;
    private static ComDeviceHelper g_comHelp;

    private String sfzpath;

    private TextView m_editMsg;

    private int m_DevFD;
    private Set<String> m_CmdString = new HashSet<>();

    private ImageView m_imgview;

    private PreviewView previewView;
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
    private ImageCapture imageCapture;
    private ExecutorService cameraExecutor;
    private com.aliyun.facebody20191230.Client client;

    private String infoChmsg;

    private static final int REQUEST_CODE_PERMISSIONS = 10;
    private static final String[] REQUIRED_PERMISSIONS = new String[]{
            Manifest.permission.CAMERA,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };




    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case CHANGE_TEXT: {
                    if (m_editMsg.getText().length() >= 3 * 1024) {
                        m_editMsg.setText("");
                    }
                    String info = (String) msg.obj;
                    m_editMsg.append(info + "\r\n");
                    break;
                }
                case CLEAR_TEXT:{
                    m_editMsg.setText("");
                    break;
                }
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 全屏显示
        requestWindowFeature(Window.FEATURE_NO_TITLE);// 无标题
        setContentView(R.layout.activity_face);

        g_usbHelp = new UsbDeviceHelper(this);
        g_comHelp = new ComDeviceHelper();

        sfzpath = this.getCacheDir().getAbsolutePath() + "/zp.bmp";

        cameraExecutor = Executors.newSingleThreadExecutor();

        initView();
        initClient(); //阿里云人脸检测

        if (allPermissionsGranted()) {
            startCamera();
        } else {
            ActivityCompat.requestPermissions(
                    this,
                    REQUIRED_PERMISSIONS,
                    REQUEST_CODE_PERMISSIONS
            );
        }

        findViewById(R.id.btn_start_compare).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            readIDCardInfo();
            //takePictureAndCompareFaces("/data/user/0/com.example.sdtreader/cache/zp.bmp");
            }
        });
    }


    private boolean allPermissionsGranted() {
        for (String permission : REQUIRED_PERMISSIONS) {
            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(
            int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                startCamera();
            } else {
                Toast.makeText(this,
                        "Permissions not granted by the user.",
                        Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    private void ShowTips(int what, String info) {
        Message msg = new Message();
        msg.what = what;
        msg.obj = info;
        handler.sendMessageDelayed(msg, 2);
    }

    private void initView() {

        m_imgview = findViewById(R.id.imgView2);
        m_editMsg = findViewById(R.id.editMsg2);
        previewView = findViewById(R.id.iv_scene);

        m_editMsg.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
        m_editMsg.setGravity(Gravity.TOP);
        m_editMsg.setSingleLine(false);
        m_editMsg.setHorizontallyScrolling(false);//水平滚动
        m_editMsg.setKeyListener(null);// 禁止输入
        m_editMsg.setMovementMethod(ScrollingMovementMethod.getInstance());

        InitCmdList();

        List<String> comList = new ArrayList<>();
        String[] arrayComPath = null;
        try {
            arrayComPath = g_comHelp.getAllDevicesPath();
        } catch (Throwable ex) {
            ex.printStackTrace();
        }
        if (arrayComPath != null && arrayComPath.length > 0) {
            for (int i = 0; i < arrayComPath.length; i++) {
                String cmd = "chmod 777 " + arrayComPath[i] + ";";
                m_CmdString.add(cmd);
                comList.add(arrayComPath[i]);
            }
        } else {
            comList.add("/dev/ttyS0");
        }
        // ShellCommandExecutor.chmodShell(m_CmdString); // 移除 chmod 命令调用

        openDevice();
    }

    private void startCamera() {
        cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                bindPreview(cameraProvider);
            } catch (Exception e) {
                Log.e("FaceActivity", "Error starting camera", e);
            }
        }, ContextCompat.getMainExecutor(this));
    }

    private void bindPreview(ProcessCameraProvider cameraProvider) {
        Preview preview = new Preview.Builder().build();
        CameraSelector cameraSelector = new CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_FRONT) // 使用前置摄像头
                .build();

        preview.setSurfaceProvider(previewView.getSurfaceProvider());

        imageCapture = new ImageCapture.Builder()
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                .build();

        cameraProvider.unbindAll();
        cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);
    }
    

    private void openDevice() {
        int ret = 0;
            String strtype = "USB"; // Default to USB

            if(strtype.equals("COM")){
                int baud = 115200; // Default baud rate
                List<String> comList = new ArrayList<>();
                String strdevpath = comList.get(0); // Default to first available COM port
                byte[] devPath = new byte[0];
                devPath = strdevpath.getBytes();
                ret = JNISDTReader._SDT_OpenComBypath(devPath,baud);
            }else{

                //USB
                m_DevFD = g_usbHelp.getUsbFileDescriptor(0x0400,0xC35A);
                if(m_DevFD <= 0){
                    m_DevFD = g_usbHelp.getUsbFileDescriptor(0x0483,0x5652);
                }
                if(m_DevFD<=0){
                    ShowTips(1,"获取设备描述符失败,return = " + m_DevFD);
                    return;
                }
                //获取设备SELinux运行模式是否为强制模式
                String mode = ShellCommandExecutor.getSELinuxMode();
                //强制模式，代表 SELinux 运作中，且已经正确的开始限制 domain/type 了

                if(mode.equals("Enforcing")){
                    String strdevpath = g_usbHelp.getUsbDevPath();
                    byte[] devPath = new byte[0];
                    devPath = strdevpath.getBytes();

                    ret = JNISDTReader._SDT_OpenUsbByPath(m_DevFD,devPath);
                    //ret = JNISDTReader._SDT_OpenPort(1001,1,devPath,m_DevFD);
                }else{
                    //root 情况下也可以通过fd打开设备
                    ret = JNISDTReader._SDT_OpenUsbByFD(m_DevFD);
                    //ret = JNISDTReader._SDT_OpenPort(1001,0,null,m_DevFD);
                }
            }
            if(ret == 0x90){
                ShowTips(1, "打开设备成功.");
                ret = JNISDTReader._SDT_GetSAMStatus();
                if(ret == 0x90){
                    ShowTips(1, "SAM_A 正常,返回值:" + ret);
                }else{
                    ShowTips(1, "自检失败,返回值:" + ret);
                }
            }else{
                ShowTips(1, "打开设备失败,返回值:." + ret);
            }
    }

    private void InitCmdList() {
        // 移除所有 chmod 命令，这些命令通常需要 root 权限
    }

    @Override
    public void onDestroy() {
        JNISDTReader._SDT_ClosePort();
        if (cameraExecutor != null) {
            cameraExecutor.shutdown();
        }
        super.onDestroy();
    }

    private void readIDCardInfo() {
        // Removed device open logic from here
        int flag = 0;
        //RadioButton radioButton = (RadioButton)findViewById(m_radioFig.getCheckedRadioButtonId());
        //radioButton.getText().toString();

        //读卡
        byte[] pucManaInfo = new byte[8];
        byte[] pucManaMsg = new byte[8];
        byte[] pucCHMsg = new byte[260];
        byte[] pucPHMsg = new byte[1032];
        byte[] pucFPMsg = new byte[1032];
        int[] puiCHMsgLen = new int[2];
        int[] puiPHMsgLen = new int[2];
        int[] puiFPMsgLen = new int[2];
        int ret = 0;
        //寻卡
        //选卡
        //读卡
        ret = JNISDTReader._SDT_StartFindIDCard(pucManaInfo);//4 个字节 0x00
        ret = JNISDTReader._SDT_SelectIDCard(pucManaMsg);    //8 个字节 0x00

        puiFPMsgLen[0] = 0;
        ret = JNISDTReader._SDT_ReadBaseMsg(pucCHMsg,puiCHMsgLen,//文字信息不得小于 256 字节
                pucPHMsg,puiPHMsgLen);//相片信息不得小于 1024 字节
        Log.d("_SDT_ReadBaseMsg", "_SDT_ReadBaseMsg" + ret);
        if(ret != 0x90){
            ShowTips(1, "读取失败,错误码:" + ret);
            return;
        }else
        {
            //ShowTips(1, "读取成功:" + puiCHMsgLen[0] + ","  +puiFPMsgLen[0] + ","  + puiPHMsgLen[0]);
            //return;
        }

        IDCardMsg idinfo = new IDCardMsg();
        //解析文字数据
        ret = idinfo.ParseIDMsg(pucCHMsg,puiCHMsgLen[0]);
        if(ret != 0){
            ShowTips(1, "文字信息解析失败." + ret);
            return;
        }
        ShowTips(0, "");
        //显示信息
        String chmsg;
        if(idinfo.getIDType().equals("I") || idinfo.getIDType().equals("Y")){
            //2017版外国人永久居留证 新版外国人永久居留证
            chmsg = idinfo.getEngName() + "|" + idinfo.getSex() + "|" + idinfo.getID() + "|"
                    + idinfo.getNationality()+ "|"  + idinfo.getName() + "|" + idinfo.getStartDate() + "|"
                    + idinfo.getEndDate() + "|" + idinfo.getBirthday() + "|" +idinfo.getSignNum()+ "|"
                    + idinfo.getIssue() + "|" + idinfo.getReverse() + "|" + idinfo.getIDNum() + "|" + idinfo.getNationalityCode() +"|";
        }else if(idinfo.getIDType().equals("J")){
            //港澳台
            chmsg = idinfo.getName() + "|" + idinfo.getSex() + "|"
                    + idinfo.getBirthday() + "|" + idinfo.getAddr()+ "|"  + idinfo.getID() + "|"
                    + idinfo.getIssue() + "|" + idinfo.getStartDate() + idinfo.getEndDate() + "|" + idinfo.getPassID() + "|"
                    + idinfo.getSignNum() +  "|" + idinfo.getReverse();
        }else{
            //身份证
            chmsg = idinfo.getName() + "|" + idinfo.getSex() + "|"  + idinfo.getNation() + "|"
                    + idinfo.getBirthday() + "|" + idinfo.getAddr()+ "|"  + idinfo.getID() + "|"
                    + idinfo.getIssue() + "|" + idinfo.getStartDate() +  "|"  +idinfo.getEndDate() + "|" + idinfo.getReverse();
        }
        infoChmsg = chmsg;
        ShowTips(1, "文字信息:" + chmsg);
        if(puiFPMsgLen[0] > 0){
            String fpinfo = idinfo.ParseIDFpMsg(pucFPMsg,puiFPMsgLen[0]);
            ShowTips(1, "指纹信息:" + fpinfo);
        }

        //解析照片信息
        idinfo.setZpPath(sfzpath);
        ret = idinfo.ParseIDPHMsg(pucPHMsg,puiPHMsgLen[0]);
        if(ret != 1){
            ShowTips(1, "身份证解码失败." + ret);
        }
        else{
            //m_imgview.setImageResource(R.drawable.*);//前景
            //m_imgview.setBackgroundResource(R.drawable.*);//背景
            m_imgview.setScaleType(ImageView.ScaleType.CENTER_INSIDE);//按比例缩放图片，使得图片长 (宽)的小于等于视图的相应维度
            //路径
            //m_imgview.setImageURI(Uri.fromFile(new File(idinfo.getZpPath())));

            //流转化成Bitmap对象
            m_imgview.setImageBitmap(getLoacalBitmap(idinfo.getZpPath()));

            ShowTips(1, "身份证解码成功,保存路径：" + idinfo.getZpPath());
            Log.d("tag","身份证解码成功,保存路径：: "+idinfo.getZpPath());
            // 拍照并进行人脸比对
            takePictureAndCompareFaces(idinfo.getZpPath());
        }
    }

    private void takePictureAndCompareFaces(String idCardPhotoPath) {
        if (imageCapture == null) {
            ShowTips(1, "相机未准备好，无法拍照。");
            return;
        }

        // 创建文件用于保存照片
        File photoFile = new File(getCacheDir(), System.currentTimeMillis() + ".jpg");
        ImageCapture.OutputFileOptions outputOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build();

        imageCapture.takePicture(
                outputOptions,
                cameraExecutor,
                new ImageCapture.OnImageSavedCallback() {
                    @Override
                    public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                        String cameraPhotoPath = photoFile.getAbsolutePath();
                        Log.d("tag","证件照地址: "+idCardPhotoPath);
                        Log.d("tag","相机照片保存成功: "+cameraPhotoPath);
//                        ShowTips(1, "相机照片保存成功: " + cameraPhotoPath);
                        ShowTips(1, "两张图片地址: " + cameraPhotoPath+";---"+idCardPhotoPath);
                        // 在主线程执行人脸比对
                        runOnUiThread(() -> {
                            // 假设您已经获取了正确的图片路径
//                            String idCardPath = "/storage/emulated/0/fei/id_card_photo.png"; // 替换为您的实际路径
//                            String cameraPath = "/storage/emulated/0/fei/camera_photo.png"; // 替换为您的实际路径
//                            faceContrast(idCardPath, cameraPath);
                            faceContrast(idCardPhotoPath, cameraPhotoPath);
                        });
                    }

                    @Override
                    public void onError(@NonNull ImageCaptureException exception) {
                        Log.e("FaceActivity", "拍照失败: " + exception.getMessage(), exception);
                        ShowTips(1, "拍照失败: " + exception.getMessage());
                    }
                }
        );
    }

    public Bitmap getLoacalBitmap(String url) {
        try {
            FileInputStream fis = new FileInputStream(url);
            return BitmapFactory.decodeStream(fis);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    private void initClient() {
        // 创建AccessKey ID和AccessKey Secret，请参考https://help.aliyun.com/document_detail/175144.html
        // 如果您使用的是RAM用户的AccessKey，还需要为子账号授予权限AliyunVIAPIFullAccess，请参考https://help.aliyun.com/document_detail/145025.html
        // 使用正确的AccessKey初始化
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                .setAccessKeyId("LTAI5tCExZmsjfns5XWYtSGr")
                .setAccessKeySecret("utTs8kXkW8HDDJe8EGj107mOy7lxk5");
        // 访问的域名
        config.endpoint = "facebody.cn-shanghai.aliyuncs.com";
        try {
            client = new com.aliyun.facebody20191230.Client(config);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void faceContrast(String idCardPhotoPath, String  cameraPhotoPath) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                InputStream idCardInputStream = null;
                InputStream cameraInputStream = null;
                try {
                    // 使用文件，文件通过inputStream传入接口。
                    idCardInputStream = new FileInputStream(new File(idCardPhotoPath));
                    cameraInputStream = new FileInputStream(new File(cameraPhotoPath));

                    CompareFaceAdvanceRequest compareFaceAdvanceRequest = new CompareFaceAdvanceRequest()
                            .setImageURLAObject(idCardInputStream)
                            .setImageURLBObject(cameraInputStream);

                    
                    RuntimeOptions runtime = new RuntimeOptions();

                    // 复制代码运行请自行打印 API 的返回值
                    CompareFaceResponse compareFaceResponse = client.compareFaceAdvance(compareFaceAdvanceRequest, runtime);
                    // 获取整体结果
                    runOnUiThread(() -> {
                        Toast.makeText(FaceActivity.this, com.aliyun.teautil.Common.toJSONString(TeaModel.buildMap(compareFaceResponse)), Toast.LENGTH_SHORT).show();
                    });
                    Log.d("SDKDemoActivity","获取整体结果: "+ Common.toJSONString(TeaModel.buildMap(compareFaceResponse)));

                    // 检查人脸对比结果
                    if (compareFaceResponse != null && compareFaceResponse.getBody() != null && compareFaceResponse.getBody().getData() != null) {
                        // 从Data对象中获取Confidence值
                        Float confidence = compareFaceResponse.getBody().getData().getConfidence();
                        
                        if (confidence != null) {
                            // 设置阈值为70.0
                            boolean isMatch = confidence > 70.0;

                            if (isMatch) {
                                Intent intent = new Intent(FaceActivity.this, SuccessActivity.class);
                                intent.putExtra("cameraPhotoPath", cameraPhotoPath);
                                intent.putExtra("idCardInfo", infoChmsg);
                                startActivity(intent);
                            } else {
                                runOnUiThread(() -> ShowTips(1, "人脸对比不匹配，相似度：" + String.format("%.2f", confidence) + "%，请重试。"));
                            }
                        } else {
                            runOnUiThread(() -> ShowTips(1, "无法获取人脸对比相似度。"));
                        }
                    } else {
                        runOnUiThread(() -> ShowTips(1, "人脸对比结果获取失败或数据结构不完整。"));
                    }


                } catch (TeaException teaException) {
                    // 获取整体报错信息
                    Log.e("FaceActivity","TeaException 报错信息: "+ Common.toJSONString(teaException));
                    // 获取单个字段
                    Log.e("FaceActivity","TeaException RequestId: "+teaException.getData().get("RequestId"));
                    runOnUiThread(() -> ShowTips(1, "人脸对比失败 (TeaException): " + teaException.getMessage()));
                } catch (FileNotFoundException e) {
                    Log.e("FaceActivity", "文件未找到: " + e.getMessage(), e);
                    runOnUiThread(() -> ShowTips(1, "人脸对比失败 (文件未找到): " + e.getMessage()));
                } catch (Exception e) {
                    Log.e("FaceActivity","未知异常: "+e.getMessage(), e);
                    runOnUiThread(() -> ShowTips(1, "人脸对比失败 (未知异常): " + e.getMessage()));
                } finally {
                    // 确保输入流被关闭
                    try {
                        if (idCardInputStream != null) {
                            idCardInputStream.close();
                        }
                        if (cameraInputStream != null) {
                            cameraInputStream.close();
                        }
                    } catch (IOException ioException) {
                        Log.e("FaceActivity", "关闭输入流失败: " + ioException.getMessage(), ioException);
                    }
                    infoChmsg = null;
                }
            }
        }).start();

    }
}